//
//  GPVideoCallManager.m
//  Keping
//
//  Created by 23 on 2017/12/10.
//  Copyright © 2017年 柯平. All rights reserved.
//

#import "GPVideoCallManager.h"
#import "GPVideoView.h"
#import <AVFoundation/AVFoundation.h>
#import "GPChatViewModel.h"
#import "GPContactRequest.h"
#import "GPProfileItem.h"
#import "AppGlobal.h"
#import "GPAudioManager.h"

@interface GPVideoCallManager () <EMCallManagerDelegate, GPVideoViewDelegate>

#pragma mark - 属性
/**当前的videoView*/
@property(nonatomic,weak) GPVideoView *videoView;
/**通话时长计时器*/
@property(nonatomic,weak) NSTimer *timer;
/**通话时长*/
@property(nonatomic,assign) double voiceTime;

#pragma mark - 属性
/**当前的通话id*/
@property(nonatomic,copy) NSString *callId;
/**当前正在通话中的session*/
@property(nonatomic,strong) EMCallSession *session;
/**当前通话的对方hid(电话号码)*/
@property(nonatomic,copy) NSString *username;

#pragma mark - 记录属性
/**是否在通话中*/
@property(nonatomic,assign) BOOL isCalling;
/**是否是后置摄像头*/
@property(nonatomic,assign) BOOL isBackCamera;


@end

@implementation GPVideoCallManager

static id _instance;

+ (instancetype)shareManager
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[self alloc] init];
    });
    return _instance;
}

- (instancetype)init
{
    if (self = [super init]) {
        
        //注册实时通话回调
        [[EMClient sharedClient].callManager addDelegate:self delegateQueue:nil];
        
        self.isCalling = NO;
        
    }
    return self;
}

- (void)dealloc
{
    if (self.timer) {
        [self.timer invalidate];
    }
    [[EMClient sharedClient].callManager removeDelegate:self];
}


//显示音视频view
- (void)showVideoView
{
    if (self.videoView) {
        [self.videoView removeFromSuperview];
    }
    
    [[UIApplication sharedApplication].keyWindow endEditing:YES];
    GPVideoView *videoView = [GPVideoView videoView];
    videoView.delegate = self;
    videoView.frame = [UIScreen mainScreen].bounds;
    [videoView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapVideoView)]];
    [videoView addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(swipeVideoView:)]];
    [[UIApplication sharedApplication].keyWindow addSubview:videoView];
    self.videoView = videoView;
    
    //记录
    self.isCalling = YES;
    
    //更新姓名头像等信息
    [self loadAvatorAndNameWithHid:self.username];
    
    NSURL *url = [[NSBundle mainBundle] URLForResource:@"sound_calling.mp3" withExtension:nil];
    [GPAudioManager.shareManger playWithURL:url];
}

//隐藏yinshipinview
- (void)hideVideoView
{
//    if (self.timer) {
//        [self.timer invalidate];
//        self.voiceTime = 0;
//    }
    
    if (self.session) {
        [self.session.localVideoView removeFromSuperview];
        [self.session.remoteVideoView removeFromSuperview];
    }
    
    if (self.videoView) {
        [self.videoView removeFromSuperview];
    }
    
    self.isCalling = NO;
    self.callId = nil;
    self.session = nil;
    
    [GPAudioManager.shareManger endPlay];
    
}

- (void)startCall:(EMCallType)type username:(NSString *)username ext:(NSString *)ext
{
    
    if (username == nil || username.length == 0) {
        NSException *exception = [NSException exceptionWithName:@"NSExceptionNULLName" reason:@"username 不能为空" userInfo:nil];
        [exception raise];
        return;
    }
    
    self.username = username;
    
    [self showVideoView];
    [self.videoView updateUIWithStatus:GPVideoViewStatusCalling];
    
    WEAKSELF
    [[EMClient sharedClient].callManager startCall:type remoteName:username ext:ext completion:^(EMCallSession *aCallSession, EMError *aError) {
        if (aError) {
            [weakSelf hideVideoView];
            UIAlertController *vc =  [UIAlertController alertControllerWithTitle:nil message:aError.errorDescription preferredStyle:UIAlertControllerStyleAlert];
            [vc addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:nil]];
            [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:vc animated:YES completion:nil];
            return ;
        }
        
        //保存
        weakSelf.callId = aCallSession.callId;
        weakSelf.session = aCallSession;
        
    }];
    
}

//开始记录语音通话时长
- (void)beginVoiceTimer
{
    [GPAudioManager.shareManger endPlay];
    
    if (self.timer) {
        [self.timer invalidate];
    }
    
    self.voiceTime = 0;
    NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timeCount) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    self.timer = timer;
}

- (void)timeCount
{
    //通话时长变化
    self.voiceTime++;
    
    //更新通话时长
    [self.videoView updateVoiceTimesecond:self.voiceTime];
}



#pragma mark - action
- (void)tapVideoView
{
    //放大，恢复
    self.videoView.layer.transform = CATransform3DIdentity;
    self.videoView.center = [UIApplication sharedApplication].keyWindow.center;
    
    //恢复UI
    [self.videoView recoveryUI];
}

- (void)swipeVideoView:(UIPanGestureRecognizer *)recognizer
{
    UIView *view = [UIApplication sharedApplication].keyWindow;
    
    CGPoint translation = [recognizer translationInView:view];
    CGPoint newCenter = CGPointMake(recognizer.view.center.x+ translation.x,
                                    recognizer.view.center.y + translation.y);//    限制屏幕范围：
    newCenter.y = MAX(recognizer.view.frame.size.height/2, newCenter.y);
    newCenter.y = MIN(view.frame.size.height - recognizer.view.frame.size.height/2,  newCenter.y);
    newCenter.x = MAX(recognizer.view.frame.size.width/2, newCenter.x);
    newCenter.x = MIN(view.frame.size.width - recognizer.view.frame.size.width/2,newCenter.x);
    recognizer.view.center = newCenter;
    [recognizer setTranslation:CGPointZero inView:view];
    
    //手势结束
    if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled) {
        
        CGPoint translation = [recognizer translationInView:view];
        CGPoint newCenter = CGPointMake(recognizer.view.center.x+ translation.x,
                                        recognizer.view.center.y + translation.y);//    限制屏幕范围：
        if (newCenter.x <= view.bounds.size.width * 0.5) {
            newCenter.x = recognizer.view.frame.size.width * 0.5;
        }else{
            newCenter.x = view.bounds.size.width - 0.5 * recognizer.view.frame.size.width;
        }
        
        [UIView animateWithDuration:0.25 animations:^{
            recognizer.view.center = newCenter;
            [recognizer setTranslation:CGPointZero inView:view];
        }];
        
    }
}


#pragma mark - 工具方法
//根据环信id更新对方的姓名和头像信息
- (void)loadAvatorAndNameWithHid:(NSString *)hid
{
    NSArray *arrayM = [GPProfileItem selectDBWithHid:hid];
    if (arrayM.count) {
        GPProfileItem *profile = arrayM.firstObject;
        NSString *url = [KGetImageURL stringByAppendingPathComponent:profile.avatarURL];
        [self.videoView updateUserInfoWithName:profile.name avator:nil avatorPath:url];
        return;
    }
    
    WEAKSELF
    NSString *url = [@"/intelligentcommunity/api/biz/ou/v1/partys/getPhone/{phone}.htm" stringByReplacingOccurrencesOfString:@"{phone}" withString:hid];
    GPContactRequest *request = [[GPContactRequest alloc] initWithURL:url];
    [request startWithCompletionBlockWithSuccess:^(__kindof KBaseRequest * _Nonnull request) {
        
        NSDictionary *dict = request.responseJSONObject;
        NSDictionary *partyView = dict[@"partyView"];
        NSLog(@">>>>>>>>>>>>>smallyou:获取用户消息--->%@", partyView);
        //创建GPProfileItem
        GPProfileItem *item = [[GPProfileItem alloc] init];
        item.uid  = partyView[@"id"];
        item.hid  = partyView[@"phone"];
        item.name = partyView[@"nickName"];
        item.phone = partyView[@"phone"];
        item.avatarURL = partyView[@"profile"];
        item.realName = partyView[@"realName"];
        item.isBlock = partyView[@"isBlock"];
        item.remarks = partyView[@"remarks"];
        [item insertToDatabase];
        //发起通知
        [GPNoticationHelp postNotificationName:kBuddyUserInfoUpdatedNotificaiton object:nil];
        
        
        dispatch_async(dispatch_get_main_queue(), ^{
            [weakSelf.videoView updateUserInfoWithName:item.name avator:nil avatorPath:item.avatarURL];
        });
        
    } failure:^(__kindof KBaseRequest * _Nonnull request) {
        NSLog(@">>>>>>>>>>>>>smallyou:获取用户消息失败--->");
    }];
}


#pragma mark - GPVideoViewDelegate

- (void)videoView:(GPVideoView *)videoView isMinisizeWindow:(BOOL)isMinisize
{
    if (isMinisize) {
        //缩小
        self.videoView.layer.transform = CATransform3DMakeScale(0.2, 0.2, 1);
        
    }else{
        self.videoView.layer.transform = CATransform3DIdentity;
        self.videoView.center = [UIApplication sharedApplication].keyWindow.center;
    }
}

/**被叫 - 同意通话*/
- (void)videoView:(GPVideoView *)videoView didReceiveBtnClicked:(KLVideoCallButton *)receiveButton
{
    //同意通话
    EMError *error = [[EMClient sharedClient].callManager answerIncomingCall:self.callId];
    if (!error) {
        //创建通话视图
        //----创建本地的view
        EMCallLocalView *localView = [[EMCallLocalView alloc] initWithFrame:CGRectMake(self.videoView.bounds.size.width - 120 - 20, 30, 120, 180)];
        localView.userInteractionEnabled = NO;
        self.session.localVideoView = localView;
        [self.videoView insertSubview:localView atIndex:0];
        
        //---创建远程view
        EMCallRemoteView *remoteView = [[EMCallRemoteView alloc] initWithFrame:self.videoView.bounds];
        remoteView.userInteractionEnabled = NO;
        remoteView.scaleMode = EMCallViewScaleModeAspectFill;
        self.session.remoteVideoView = remoteView;
        [self.videoView insertSubview:remoteView atIndex:0];

        //切换视图状态
        if (self.session.type == EMCallTypeVideo) {
            //视频通话状态
            [self.videoView updateUIWithStatus:GPVideoViewStatusVideoSession];
            
            //开启通话时长计时
            [self beginVoiceTimer];
        }else{
            //音频通话状态
            [self.videoView updateUIWithStatus:GPVideoViewStatusVoiceSession];
            
            //开启通话时长计时
            [self beginVoiceTimer];
        }
    }
    
    [GPAudioManager.shareManger endPlay];
}

/**被叫 - 拒绝通话*/
- (void)videoView:(GPVideoView *)videoView didRejectBtnClicked:(KLVideoCallButton *)rejectButton
{
    //拒绝通话
    [[EMClient sharedClient].callManager endCall:self.callId reason:EMCallEndReasonDecline];
    
    [GPAudioManager.shareManger endPlay];
}

/**主叫 - 取消*/
- (void)videoView:(GPVideoView *)videoView didCancelCalling:(KLVideoCallButton *)rejectButton
{
    //取消
    EMError *error = [[EMClient sharedClient].callManager endCall:self.callId reason:EMCallEndReasonHangup];
    if (!error) {
        
        [self hideVideoView];
    }
    
    [GPAudioManager.shareManger endPlay];
}

/**接通中 - 主动挂断*/
- (void)videoView:(GPVideoView *)videoView didHangupSession:(KLVideoCallButton *)rejectButton
{
    //主动挂断
    EMError *error = [[EMClient sharedClient].callManager endCall:self.callId reason:EMCallEndReasonHangup];
    if (!error) {
        
        [self hideVideoView];
    }
    
    [GPAudioManager.shareManger endPlay];
    
}

/**接通中 - 切换摄像头*/
- (void)videoView:(GPVideoView *)videoView didChangeCamera:(KLVideoCallButton *)changeButton
{
    self.isBackCamera = !self.isBackCamera;
    [self.session switchCameraPosition:!self.isBackCamera];
}

/**接通中 - 从视频切换成语音*/
- (void)videoView:(GPVideoView *)videoView didSwitchToVoice:(UIButton *)switchButton
{
    //隐藏视频显示图层
    [self.session.localVideoView removeFromSuperview];
    [self.session.remoteVideoView removeFromSuperview];

    //暂停视频图像的传播
    [self.session pauseVideo];
    
    
    //根据状态切换UI
    [self.videoView updateUIWithStatus:GPVideoViewStatusVoiceSession];
}

/**接通中 - 免提*/
- (void)videoView:(GPVideoView *)videoView didHandsOff:(BOOL)isHandsOff
{
    if (isHandsOff) {
        //扬声器播放
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
//        [[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
        NSLog(@"扬声器播放");
    }else{
        //听筒播放
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
//        [[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:nil];
        NSLog(@"听筒播放");
    }
    
//    [[AVAudioSession sharedInstance] setActive:YES error:nil];
    
}

/**接通中 - 静音*/
- (void)videoView:(GPVideoView *)videoView didSlienceVoice:(BOOL)isSlience
{
    //暂停语音传输
    if (isSlience) {
        [self.session pauseVoice];
    }else{
        [self.session resumeVoice];
    }
}


#pragma mark - EMCallManagerDelegate
/*!
 *  \~chinese
 *  用户A拨打用户B，用户B会收到这个回调
 *
 *  @param aSession  会话实例
 */
- (void)callDidReceive:(EMCallSession *)aSession
{
    //如果有通话正在进行中，则占线拒接
    if (self.isCalling) {
        [[EMClient sharedClient].callManager endCall:aSession.callId reason:EMCallEndReasonBusy];
        return;
    }
    
    //记录当前的callid及session
    self.callId = aSession.callId;
    self.session = aSession;
    self.username = aSession.remoteName;
    
    //显示被叫view
    [self showVideoView];
    
    //更新视图状态
    [self.videoView updateUIWithStatus:GPVideoViewStatusCalled];
    
    
}

/*!
 *  \~chinese
 *  1. 用户A或用户B结束通话后，双方会收到该回调
 *  2. 通话出现错误，双方都会收到该回调
 */
- (void)callDidEnd:(EMCallSession *)aSession reason:(EMCallEndReason)aReason error:(EMError *)aError
{
    //根据剩余的秒数，计算所需要的小时数、分钟数和秒数
    int hours = (int)self.voiceTime / 3600;
    int last1 = (int)self.voiceTime % 3600;
    int minutes = last1 / 60;
    int seconds = last1 % 60;
    NSString *msgText;
    if (hours == 0) {
        msgText = [NSString stringWithFormat:@"%@Call %02zd:%02zd",  (aSession.type == EMCallTypeVideo?@"Video ":@"Voice"), minutes, seconds];
    }else{
        msgText = [NSString stringWithFormat:@"%@Call %02zd:%02d:%02zd", (aSession.type == EMCallTypeVideo?@"Video ":@"Voice"), hours, minutes, seconds];
    }
    EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:msgText];
    EMMessage *message = nil;
    //本地的聊天记录插入通话消息
    if (aSession.isCaller) {
        //主叫
        message = [[EMMessage alloc] initWithConversationID:aSession.remoteName from:aSession.localName to:aSession.remoteName body:body ext:nil];
        message.direction = EMMessageDirectionSend;
        EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:aSession.remoteName type:EMConversationTypeChat createIfNotExist:YES];
        [conversation insertMessage:message error:nil];
    }else{
        //被叫
        message = [[EMMessage alloc] initWithConversationID:aSession.remoteName from:aSession.remoteName to:aSession.localName body:body ext:nil];
        message.direction = EMMessageDirectionReceive;
        EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:aSession.remoteName type:EMConversationTypeChat createIfNotExist:YES];
        [conversation insertMessage:message error:nil];
    }
    
    if (self.timer) {
        [self.timer invalidate];
        self.voiceTime = 0;
    }
    
    //隐藏view
    [self hideVideoView];
    
    //提示错误
    NSString *title = @"";
    if (aReason == EMCallEndReasonDecline) {
        title = @"对方已挂断";
    }else if (aReason == EMCallEndReasonNoResponse){
        title = @"暂时没有人接听";
    }else if (aReason == EMCallEndReasonBusy){
        title = @"对方正在通话中";
    }else if (aReason == EMCallEndReasonRemoteOffline){
        title = @"对方不在线";
    }
    
    //发出通知，视频音频通话已结束
    dispatch_async(dispatch_get_main_queue(), ^{
        [[NSNotificationCenter defaultCenter] postNotificationName:kVideoVoiceCallEndNotification object:message];
    });
    
    
    if (title.length) {
        
        UIAlertController *vc = [UIAlertController alertControllerWithTitle:nil message:title preferredStyle:UIAlertControllerStyleAlert];
        [vc addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            
        }]];
        [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:vc animated:YES completion:nil];
        
    }
}

/*!
 *  \~chinese
 *  用户B同意用户A拨打的通话后，用户A会收到这个回调
 *
 *  @param aSession  会话实例
 */
- (void)callDidAccept:(EMCallSession *)aSession
{
    //用户B同意A的通话，A会收到  B也会收到
    if (!aSession.isCaller) {
        return;
    }
    
    //创建通话视图
    //----创建本地的view
    EMCallLocalView *localView = [[EMCallLocalView alloc] initWithFrame:CGRectMake(self.videoView.bounds.size.width - 120 - 20, 30, 120, 180)];
    localView.userInteractionEnabled = NO;
    self.session.localVideoView = localView;
    [self.videoView insertSubview:localView atIndex:0];
    
    //---创建远程view
    EMCallRemoteView *remoteView = [[EMCallRemoteView alloc] initWithFrame:self.videoView.bounds];
    remoteView.userInteractionEnabled = NO;
    remoteView.scaleMode = EMCallViewScaleModeAspectFill;
    self.session.remoteVideoView = remoteView;
    [self.videoView insertSubview:remoteView atIndex:0];
    
    //切换视图状态
    if (self.session.type == EMCallTypeVideo) {
        //视频通话状态
        [self.videoView updateUIWithStatus:GPVideoViewStatusVideoSession];
        //开启通话时长计时
        [self beginVoiceTimer];
    }else{
        //音频通话状态
        [self.videoView updateUIWithStatus:GPVideoViewStatusVoiceSession];
        //开启通话时长计时
        [self beginVoiceTimer];
    }
}


/*!
 *  \~chinese
 *  用户A和用户B正在通话中，用户A中断或者继续数据流传输时，用户B会收到该回调
 *
 *  @param aSession  会话实例
 *  @param aType     改变类型
 */
- (void)callStateDidChange:(EMCallSession *)aSession
                      type:(EMCallStreamingStatus)aType
{
    
    NSLog(@"---->%zd", aType);
    //中断视频传输 -- 切换语音
    if (aType == EMCallStreamStatusVideoPause) {
        
        //切换语音(中断视频传输)
        [aSession pauseVideo];
        
        //隐藏视频显示图层
        [aSession.localVideoView removeFromSuperview];
        [aSession.remoteVideoView removeFromSuperview];
        
    }
}

- (void)callDidConnect:(EMCallSession *)aSession {
    if(aSession.type == EMCallTypeVideo) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            
            //初始化播放器的时候如下设置
            UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
            AudioSessionSetProperty(kAudioSessionProperty_AudioCategory,sizeof(sessionCategory),&sessionCategory);
            UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
            AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,sizeof (audioRouteOverride),&audioRouteOverride);
            
            AVAudioSession *audioSession = [AVAudioSession sharedInstance];
            //默认情况下扬声器播放
//            [audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
            [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil];
            [audioSession setActive:YES error:nil];
            
        });
    }
}


@end















